package ar.edu.uba.fi.jmit.aspecter.monitor.invocationCounter;

import java.util.Date;
import java.util.LinkedList;
import java.util.List;

import javassist.ClassPool;
import javassist.CtClass;
import javassist.NotFoundException;
import ar.edu.uba.fi.jmit.aspecter.AspecterTestCase;
import ar.edu.uba.fi.jmit.aspecter.core.Constants;
import ar.edu.uba.fi.jmit.aspecter.core.ConstructorDefinition;
import ar.edu.uba.fi.jmit.aspecter.core.MethodDefinition;
import ar.edu.uba.fi.jmit.aspecter.core.ResourceProperties;
import ar.edu.uba.fi.jmit.aspecter.core.WeavingInstrumentor;
import ar.edu.uba.fi.jmit.aspecter.monitor.testUtils.ConstructorDefinitionWithClassName;
import ar.edu.uba.fi.jmit.aspecter.monitor.testUtils.EventPriorityMock;
import ar.edu.uba.fi.jmit.aspecter.monitor.testUtils.MethodDefinitionWithClassName;
import ar.edu.uba.fi.jmit.aspecter.monitor.testUtils.MockEvent;
import ar.edu.uba.fi.jmit.aspecter.monitor.testUtils.SenderFactoryMock;
/**
 * Test del Instrumentor para el tipo de monitoreo "Method Invocation Counter"
 * @author Tomas
 *
 */
public class MethodInvocationCounterInstrumentorTestCase extends
		AspecterTestCase {
	
	public void test() throws NotFoundException {
		SenderFactoryMock.clean();
		String className = getNextClassName();
		try {
			MethodDefinition methodDefinition = new MethodDefinitionWithClassName(
					ar.edu.uba.fi.jmit.aspecter.monitor.testUtils.MonitorTarget.class,
					className,
					"theMethod", 
					new LinkedList<Class<?>>(), 
					void.class);
			WeavingInstrumentor instrumentor = new MethodInvocationCounterInstrumentor(methodDefinition, "MethodInvocationCounterInstrumentorTestCase_test", "getId()", null);
			CtClass ctClazz = ClassPool.getDefault().getAndRename("ar.edu.uba.fi.jmit.aspecter.monitor.testUtils.MonitorTarget", className);
			instrumentor.alter(ctClazz);
			Class<?> clazz = ctClazz.toClass();
//			assertNotNull(clazz.getMethod(ResourceProperties.getProperty("jmit.aspecter.eventMethodName"), Class.forName(ResourceProperties.getProperty("jmit.sender.eventClassName"))));
			Object object = clazz.newInstance();
			clazz.getMethod("setId", int.class).invoke(object, 10);
			clazz.getMethod("theMethod").invoke(object);
			List<MockEvent> list = SenderFactoryMock.getSenderInstance().getSendedEvents();
			assertEquals(1, list.size());
			assertEquals(10, list.get(0).getData().get(ResourceProperties.getProperty(Constants.EVENT_ID_OBJECT_KEY)));
			assertEquals("MethodInvocationCounterInstrumentorTestCase_test", list.get(0).getData().get(ResourceProperties.getProperty(Constants.EVENT_MONITOR_NAME_KEY)));
			assertSimilarDates(new Date(), (Date) list.get(0).getData().get(ResourceProperties.getProperty(Constants.EVENT_MONITOR_DATE)));
			assertEquals("void_ar.edu.uba.fi.jmit.aspecter.monitor.testUtils.MonitorTarget.theMethod()", list.get(0).getSource());
			assertEquals(EventPriorityMock.NORMAL, list.get(0).getPriority());
		} catch (Exception e) {
			fail(e);
		}
	}
	public void testWithConstructor() throws NotFoundException {
		SenderFactoryMock.clean();
		String className = getNextClassName();
		try {
			ConstructorDefinition constructorDefinition = new ConstructorDefinitionWithClassName(
					ar.edu.uba.fi.jmit.aspecter.monitor.testUtils.MonitorTarget.class,
					className,
					new LinkedList<Class<?>>());
			WeavingInstrumentor instrumentor = new MethodInvocationCounterInstrumentor(constructorDefinition, "MethodInvocationCounterInstrumentorTestCase_testWithConstructor", "getId()", null);
			CtClass ctClazz = ClassPool.getDefault().getAndRename("ar.edu.uba.fi.jmit.aspecter.monitor.testUtils.MonitorTarget", className);
			instrumentor.alter(ctClazz);
			Class<?> clazz = ctClazz.toClass();
			clazz.newInstance();
			List<MockEvent> list = SenderFactoryMock.getSenderInstance().getSendedEvents();
			assertEquals(1, list.size());
			assertEquals(0, list.get(0).getData().get(ResourceProperties.getProperty(Constants.EVENT_ID_OBJECT_KEY)));
			assertEquals("MethodInvocationCounterInstrumentorTestCase_testWithConstructor", list.get(0).getData().get(ResourceProperties.getProperty(Constants.EVENT_MONITOR_NAME_KEY)));
			assertSimilarDates(new Date(), (Date) list.get(0).getData().get(ResourceProperties.getProperty(Constants.EVENT_MONITOR_DATE)));
			assertEquals("ar.edu.uba.fi.jmit.aspecter.monitor.testUtils.MonitorTarget()", list.get(0).getSource());
			assertEquals(EventPriorityMock.NORMAL, list.get(0).getPriority());
			
			clazz.getConstructor(int.class).newInstance(10);
			assertEquals(1, list.size());
		} catch (Exception e) {
			fail(e);
		}
	}

}

